package uk.co.BexhillWeb.MediaManager.Managers;

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JSplitPane;

import uk.co.BexhillWeb.MediaManager.EventUtilities.CustomEvent;
import uk.co.BexhillWeb.MediaManager.EventUtilities.CustomListener;
import uk.co.BexhillWeb.MediaManager.Windows.ButtonPanel;
import uk.co.BexhillWeb.MediaManager.Windows.MainWindow;
import uk.co.BexhillWeb.PluginApi.Abstract.WindowPanel;

public class WindowManager {

	private static HashMap<String,WindowPanel> windows = new HashMap<String, WindowPanel>();
	private WindowPanel pluginManagerWindow;
	private MainWindow mainWindow = new MainWindow("MainWindow");
	
	private JPanel windowContainer = new JPanel(new BorderLayout());
	private JPanel settingsContainer = new JPanel(new BorderLayout());
	private JPanel container = new JPanel();
	
	private JPanel windowPanelContainer = new JPanel();
	private ButtonPanel buttonPanel;
	private CardLayout wcl = new CardLayout();
	private CardLayout mcl = new CardLayout();
	
	public WindowManager() {
		container.setLayout(mcl);
		
		windowContainer.setName("windows");
		settingsContainer.setName("settings");
		settingsContainer.setBackground(Color.BLACK);
		
		container.add(windowContainer,windowContainer.getName());
		container.add(settingsContainer,settingsContainer.getName());
		
		windowPanelContainer.setLayout(wcl);	
		EventManager.addMyEventListener(new CustomListener(){

			@Override
			public void EventOccurred(CustomEvent evt) {
				// TODO Auto-generated method stub
				ArrayList<Component> tempList = new ArrayList<Component>();
				for(final WindowPanel w : windows.values()){
					windowPanelContainer.add(w,w.getReadableName());
					JButton tempButton = new JButton("test");
					//tempButton.setBorder(BorderFactory.createEmptyBorder());
					//tempButton.setContentAreaFilled(false);
					tempButton.setMinimumSize(new Dimension(80, 80));
					
			        tempButton.addActionListener(new ActionListener() {
			                public void actionPerformed(ActionEvent arg0) {
			                	mcl.show(container, "windows");
			                	wcl.show(windowPanelContainer, w.getReadableName());
			                }
			        });
			        tempList.add(tempButton);
			        mainWindow.invalidate();
					mainWindow.validate();
				}
				buttonPanel = new ButtonPanel(tempList);
				JPanel tempPanel = new JPanel();
				tempPanel.setLayout(new FlowLayout());
				tempPanel.add(buttonPanel);
				JSplitPane j = new JSplitPane();
		        j.setResizeWeight(0.05);
		        j.setDividerSize(0);
		        j.add(tempPanel, JSplitPane.LEFT);
		        j.add(windowPanelContainer, JSplitPane.RIGHT);
		        windowContainer.add(j);
		        mainWindow.invalidate();
				mainWindow.validate();
			}
			
		});
		setupMenu();
		mainWindow.add(container);
		mainWindow.invalidate();
		mainWindow.validate();
	}
	
	


	public static void addWindow(WindowPanel w) {
		//TODO add window code
		windows.put(w.getReadableName(), w);
	}
	
	private void getWindows(){
		ArrayList<Class> tempPanels = new ArrayList<Class>();
		WindowPanel tempPanel = null; 
		try {
			tempPanels = WindowManager.getWindowPanels("uk.co.BexhillWeb.MediaManager.WindowPanels");
		} catch (ClassNotFoundException | IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		for(Class c : tempPanels){
			try {
				final String tempName = c.getName().substring(c.getName().lastIndexOf(".")+1);
				tempPanel=(WindowPanel)c.getConstructor().newInstance();
				tempPanel.setReadableName(tempName);
				
				/**
				switch(tempName){
				
				case "PluginManagerWindow" : 
					tempPanel.setWindowType(WindowType.PLUGINMANAGER); 
					pluginManagerWindow=tempPanel;
					break;
				default: 
					tempPanel.setWindowType(WindowType.INTERACTIVE); 
					windows.put(tempName,tempPanel);
					
					break;
				}
				*/
				System.out.println(tempPanel.getReadableName());
				windowPanelContainer.add(tempPanel,tempPanel.getReadableName());
				
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (SecurityException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		

		
		
		windows.put("albumArt", tempPanel);
		tempPanels = null;
	}
	
	private void setupMenu(){
		JMenuBar jBar = new JMenuBar();
		JMenu file = new JMenu();
		JMenu plugins = new JMenu();
		file.setText("File");
		JMenuItem item = new JMenuItem();
		item.setText("Open");
		file.add(item);
		item = new JMenuItem();
		item.setText("Exit");
		item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                    System.exit(0);
            }
		});
		file.addSeparator();
		file.add(item);
		
		plugins.setText("Plugins");
		item = new JMenuItem();
		item.setText("Plugin Manager");
		item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
            	mcl.show(container, "settings");
            	//wcl.show(windowPanelContainer, pluginManagerWindow.getReadableName());
            }
		});
		plugins.add(item);
		item = new JMenuItem();
		item.setText("Windows");
		item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
            	mcl.show(container, "windows");
            	//wcl.show(windowPanelContainer, pluginManagerWindow.getReadableName());
            }
		});
		plugins.add(item);
		jBar.add(file);
		jBar.add(plugins);
		mainWindow.setJMenuBar(jBar);
	}
	
	
	public boolean windowExists(String name) {
		return (windows.containsKey(name)) ?  true : false;
	}
	
	public WindowPanel getWindow(String name) {
		return (windows.containsKey(name)) ?  windows.get(name) : null;
	}
	
	/**
	  * Scans all classes accessible from the context class loader which belong to the given package and subpackages.
	  *
	  * @param packageName The base package
	  * @return The classes
	  * @throws ClassNotFoundException
	  * @throws IOException
	  */
	 public static ArrayList<Class> getWindowPanels(String packageName)
	 
	         throws ClassNotFoundException, IOException {
		 
	     ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
	     assert classLoader != null;
	     String path = packageName.replace('.', '/');
	     
	     Enumeration<URL> resources = classLoader.getResources(path);
	     List<File> dirs = new ArrayList<File>();
	     while (resources.hasMoreElements()) {
	         URL resource = resources.nextElement();
	         dirs.add(new File(resource.getFile().replace("%20", " ")));
	     }
	     ArrayList<Class> classes = new ArrayList<Class>();
	     for (File directory : dirs) {
	         classes.addAll(findClasses(directory, packageName));
	         
	     }

	     return classes;
	 }

	 /**
	  * Recursive method used to find all classes in a given directory and subdirs.
	  *
	  * @param directory   The base directory
	  * @param packageName The package name for classes found inside the base directory
	  * @return The classes
	  * @throws ClassNotFoundException
	  */
	 private static List<Class> findClasses(File directory, String packageName) throws ClassNotFoundException {
	     List<Class> classes = new ArrayList<Class>();
	     if (!directory.exists()) {
	         return classes;
	     }
	     File[] files = directory.listFiles();
	     for (File file : files) {
	    	 
	         if (file.isDirectory()) {
	             assert !file.getName().contains(".");
	             classes.addAll(findClasses(file, packageName + "." + file.getName()));
	         } else if (file.getName().endsWith(".class")) {
	             classes.add(Class.forName(packageName + '.' + file.getName().substring(0, file.getName().length() - 6)));
	         }
	     }
	     return classes;
	 }
}
